package com.poly.common.core.utils;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.poly.common.core.tools.utils.Func;

import java.sql.Timestamp;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * jdk 1.8
 * 日期时间工具类
 * Author Yang HuiJIng  Email 1073602@qq.com
 */
public class DateTimeUtil {
    /**
     * 判断字符串是否是有效的日期
     *
     * @param dateStr       --日期字符串
     * @param formatPattern --格式如 "yyyy-MM-dd,yyyy-M-d,yyyyMMdd,yyyy-MM-dd HH:mm:ss,yyyy-M-d h:m:s,yyyyMMddHHmmss"
     * @return 是则返回true，否则返回false
     */
    public static boolean isValid(String dateStr, String... formatPattern) {
        if ((dateStr == null) || (dateStr.length() < 8)) {
            return false;
        }
        if (formatPattern == null || formatPattern.length == 0) {
            formatPattern = new String[]{"yyyy-MM-dd", "yyyy-M-d", "yyyyMMdd", "yyyy-MM-dd HH:mm:ss", "yyyy-M-d h:m:s", "yyyyMMddHHmmss"};
        }
        for (String item : formatPattern) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(item);
            if (dateStr.equals(formatter.format(formatter.parse(dateStr)))) {
                return true;
            }
        }
        return false;
    }

    /**
     * 将LocalDate 转换成 String yyyy-MM-dd
     *
     * @param localDate
     * @return
     */
    public static String localDateToStr(LocalDate localDate) {
        return localDateToStr(localDate, "yyyy-MM-dd");
    }

    /**
     * 将LocalDate 转换成 String
     *
     * @param localDate
     * @param formatPattern
     * @return
     */
    public static String localDateToStr(LocalDate localDate, String formatPattern) {
        return localDate.format(DateTimeFormatter.ofPattern(formatPattern));
    }

    /**
     * LocalDateTime 转换成 String yyyy-MM-dd HH:mm:ss
     *
     * @param localDateTime
     * @return
     */
    public static String localDateTimeToStr(LocalDateTime localDateTime) {
        return localDateTimeToStr(localDateTime, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 将LocalDate 转换成 String
     *
     * @param localDateTime
     * @param formatPattern
     * @return
     */
    public static String localDateTimeToStr(LocalDateTime localDateTime, String formatPattern) {
        return localDateTime.format(DateTimeFormatter.ofPattern(formatPattern));
    }

    /**
     * 将LocalDate 转换成 Date
     *
     * @param localDate
     * @return
     */
    public static Date localDateToDate(LocalDate localDate) {
        return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }


    /**
     * 将LocalDateTime 转换成 Date
     *
     * @param localDateTime
     * @return
     */
    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 将 Date 转换成LocalDate
     *
     * @param date
     * @return
     */
    public static LocalDate dateToLocalDate(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    /**
     * 将 Date 转换成LocalDateTime
     * atZone()方法返回在指定时区从此Instant生成的ZonedDateTime。
     *
     * @param date
     * @return
     */
    public static LocalDateTime dateToLocalDateTime(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * 转换字符串为日期
     *
     * @param dateStr       --日期字符串
     * @param formatPattern --格式如 "yyyy-MM-dd,yyyy-M-d,yyyyMMdd,yyyy-MM-dd HH:mm:ss,yyyy-M-d h:m:s,yyyyMMddHHmmss"
     * @return
     */
    public static LocalDateTime stringToDateTime(String dateStr, String formatPattern) {

        DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                // 解析date+time
                .appendPattern(formatPattern)
                // 解析毫秒数
                .appendValue(ChronoField.MILLI_OF_SECOND, 3)
                .toFormatter();
//        return LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(formatPattern));
        return LocalDateTime.parse(dateStr, formatter);
    }

    /**
     * 转换字符串日期为 LocalDate
     *
     * @param dateStr       --日期字符串
     * @param formatPattern --格式如 "yyyy-MM-dd,yyyy-M-d,yyyyMMdd"
     * @return
     */
    public static LocalDate stringToDate(String dateStr, String formatPattern) {
        return LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(formatPattern));
    }

    /**
     * 转换字符串为 Timestamp
     *
     * @param dateStr       --日期字符串
     * @param formatPattern --格式如 "yyyy-MM-dd HH:mm:ss,yyyy-M-d h:m:s,yyyyMMddHHmmss"
     * @return
     */
    public static Timestamp stringToTimestamp(String dateStr, String formatPattern) {
        return dataTimeToTimestamp(stringToDateTime(dateStr, formatPattern));
    }

    /**
     * 转换字符串日期为 Timestamp
     *
     * @param dateStr       --日期字符串
     * @param formatPattern --格式如 "yyyy-MM-dd,yyyy-M-d,yyyyMMdd"
     * @return
     */
    public static Timestamp stringDateToTimestamp(String dateStr, String formatPattern) {
        return dataTimeToTimestamp(stringToDate(dateStr, formatPattern).atStartOfDay());
    }

    /**
     * 转换日期为字符串
     *
     * @param dateTime      --日期
     * @param formatPattern --格式如 "yyyy-MM-dd,yyyy-M-d,yyyyMMdd,yyyy-MM-dd HH:mm:ss,yyyy-M-d h:m:s,yyyyMMddHHmmss"
     * @return
     */
    public static String dateTimeToString(LocalDateTime dateTime, String formatPattern) {
        return dateTime.format(DateTimeFormatter.ofPattern(formatPattern));
    }


    /**
     * 取得现在的日期
     *
     * @param formatPattern --格式如 "yyyy-MM-dd,yyyy-M-d,yyyyMMdd,yyyy-MM-dd HH:mm:ss,yyyy-M-d h:m:s,yyyyMMddHHmmss"
     * @return 返回格式化的日期字符串
     */
    public static String now(String formatPattern) {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(formatPattern));
    }

    /**
     * 取得现在的日期
     *
     * @return 返回格式化的日期字符串
     */
    public static String now() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }

    /**
     * 取得现在的日期
     *
     * @return
     */
    public static Timestamp nowTime() {
        return dataTimeToTimestamp(LocalDateTime.now());
    }

    /**
     * 取得当前年初日期
     *
     * @return 返回当前年初日期
     */
    public static String getBeginDate() {
        return DateTimeUtil.now("yyyy-01-01");
    }

    /**
     * 将Long转为LocalDateTime
     *
     * @param time
     * @return
     */
    public static LocalDateTime longToDateTime(long time) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault());
    }

    /**
     * 将Timestamp转为LocalDateTime
     *
     * @param timestamp
     * @return
     */
    public static LocalDateTime timestampToDateTime(Timestamp timestamp) {
        return timestamp.toLocalDateTime();
    }

    /**
     * 转换 Timestamp 为 字符串
     *
     * @param timestamp     --Timestamp
     * @param formatPattern --格式如 "yyyy-MM-dd,yyyy-M-d,yyyyMMdd,yyyy-MM-dd HH:mm:ss,yyyy-M-d h:m:s,yyyyMMddHHmmss"
     * @return
     */
    public static String timestampToString(Timestamp timestamp, String formatPattern) {
        return dateTimeToString(timestampToDateTime(timestamp), formatPattern);
    }

    /**
     * 将LocalDataTime转为Long
     *
     * @param dateTime
     * @return
     */
    public static long dataTimeToLong(LocalDateTime dateTime) {
        return dateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
    }

    /**
     * 将LocalDataTime转为Timestamp
     *
     * @param dateTime
     * @return
     */
    public static Timestamp dataTimeToTimestamp(LocalDateTime dateTime) {
        return Timestamp.valueOf(dateTime);
    }


    /**
     * 获得日期当月最后一天日期
     *
     * @param date
     * @return
     */
    public static LocalDate getMonthLastDate(LocalDate date) {
        LocalDate date2 = date.plusMonths(1);
        return LocalDate.of(date2.getYear(), date2.getMonthValue(), 1).minusDays(1);
    }


    /**
     * 获得今天是周几
     */

    public static String getWeek(Date date) {
        String[] weekdays = {"星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
        return weekdays[DateUtil.dayOfWeek(date) - 1];
    }


    public static void main(String[] args) {
        /*System.out.println(DateUtil.getTime(DateUtil.strToDate("2019-09-12 00:00:00"), "yyyy年MM月dd日"));*/
        boolean b = DateTimeUtil.isValid("2019-09-12", "yyyy-MM-dd");
        System.out.println(b);
//        String s=  DateTimeUtil.now("yyyy-MM-dd HH:mm:ss");
//        System.out.println(s);
//         s=  DateTimeUtil.now("yyyy-M-d H:m:s");
//        System.out.println(s);
//        s=  DateTimeUtil.now("yyyy-MM-dd");
//        System.out.println(s);
//        s=  DateTimeUtil.now("HH:mm:ss");
//        System.out.println(s);
//        System.out.println(DateTimeUtil.getBeginDate());

        //Timestamp timestamp= DateTimeUtil.stringToTimestamp("2019-09-12","yyyy-MM-dd");
        //System.out.println(timestamp.getTime());
        LocalDateTime t = DateTimeUtil.stringToDateTime("2019-09-12 00:00:00", "yyyy-MM-dd HH:mm:ss");
//        LocalDate t=  DateTimeUtil.stringToDate("2019-09-12","yyyy-MM-dd");
//        System.out.println(t.toString());
//        LocalDate localDate = LocalDate.parse("2019-09-12 20:19:53", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
//        LocalDateTime t = localDate.atStartOfDay();
//        LocalDateTime t= LocalDateTime.parse("2019-09-12", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
//        System.out.println(t.toString());
//        System.out.println(DateTimeUtil.now("yyyyMMddHHmmss"));
    }


    /**
     * <判断指定时间是否大于当前时间  hours 小时>
     *
     * @param date
     * @return boolean
     * @Author Ly
     * @DateTime 2020/10/21 9:18 AM
     */
    public static boolean isDateGtTowHours(Date date, long hours) {
        if (date != null) {
            Date now = new Date();
            long nowTime = now.getTime();
            long appointTime = date.getTime();
            long resultTime = nowTime - appointTime;
            if (resultTime > TimeUnit.HOURS.toMillis(hours)) {
                return false;
            } else {
                return true;
            }
        }
        return false;
    }


    /**
     * 偏移天
     *
     * @param date   日期
     * @param offset 偏移天数，正数向未来偏移，负数向历史偏移
     * @return 偏移后的日期
     */
    public static DateTime offsetDay(Date date, int offset) {
        return offset(date, DateField.DAY_OF_YEAR, offset);
    }


    /**
     * 获取指定日期偏移指定时间后的时间，生成的偏移日期不影响原日期
     *
     * @param date      基准日期
     * @param dateField 偏移的粒度大小（小时、天、月等）{@link DateField}
     * @param offset    偏移量，正数为向后偏移，负数为向前偏移
     * @return 偏移后的日期
     */
    public static DateTime offset(Date date, DateField dateField, int offset) {
        return dateNew(date).offset(dateField, offset);
    }


    /**
     * 根据已有{@link Date} 产生新的{@link DateTime}对象
     *
     * @param date Date对象
     * @return {@link DateTime}对象
     * @since 4.3.1
     */
    public static DateTime dateNew(Date date) {
        return new DateTime(date);
    }

    /**
     * 获取两个日期的间隔时间（分钟）
     *
     * @param date1
     * @param date2
     * @return
     */
    public static long getDiffMinute(Date date1, Date date2) {
        double minute = ((double) (date1.getTime() - date2.getTime())) / (60 * 1000);
        long m = (long) Math.ceil(minute);
        return m;
    }

    /**
     * 获取两个日期的间隔时间（秒）
     *
     * @param date1
     * @param date2
     * @return
     */
    public static long getDiffSecond(Date date1, Date date2) {
        return (date1.getTime() - date2.getTime()) / (1000);
    }

    /**
     * 获取两个日期的间隔时间（秒）
     *
     * @param date1
     * @param date2
     * @return
     */
    public static long getDiffSecond(long date1, long date2) {
        return (date1 - date2) / (1000);
    }

    /**
     * 获取两个日期的间隔时间（天）
     *
     * @param date1
     * @param date2
     * @return
     */
    public static long getDiffDay(Date date1, Date date2) {
        double day = ((double) (date1.getTime() - date2.getTime())) / (24 * 60 * 60 * 1000);
        long m = (long) Math.ceil(day);

        return m;
    }

    /**
     * 　　* @description: 获取指定日期0点到24点
     * 　　* @author wjl
     *
     */
    public static Map<String, Object> covertTime(Date date) {
        if (Func.isNull(date)) {
            date = new Date();
        }
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
        LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
        LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
        // 获得某天最大时间 2020-02-19 23:59:59
        Date endTime = Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
        // 获得某天最小时间 2020-02-17 00:00:00
        Date startTime = Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
        Map<String, Object> map = new HashMap<>();
        map.put("endTime", endTime);
        map.put("startTime", startTime);
        return map;
    }

    public static List<LocalDateTime> get24Hours() {
        LocalDateTime minus = LocalDateTime.now().minus(24, ChronoUnit.HOURS);
        List<LocalDateTime> localTimeList = new ArrayList<>();
        for (int i = 0; i < 24; i++) {
            minus = minus.plus(1, ChronoUnit.HOURS);
            localTimeList.add(LocalDateTime.of(minus.toLocalDate(),LocalTime.of(minus.toLocalTime().getHour(), 0)));
        }
        return localTimeList;
    }

    public static List<String> get24HoursAdd() {
        List<String> localTimeList = new ArrayList<>();
        LocalDateTime minus = LocalDateTime.now().minus(24, ChronoUnit.HOURS);
        for (int i = 0; i < 24; i++) {
            // 将LocalTime对象转换为字符串
            minus = minus.plus(1, ChronoUnit.HOURS);
            String timeStr = minus.format(DateTimeFormatter.ofPattern("HH"));
            localTimeList.add(timeStr);
        }
        return localTimeList;
    }


    public static LocalTime dateToLocalTime(Date date) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zonedDateTime = date.toInstant().atZone(zoneId);
        return zonedDateTime.toLocalTime();
    }

    public static Map<String,String> getWeekMaps() {
        Map<String, String> map = new HashMap<>();
        map.put("1","周一");
        map.put("2","周二");
        map.put("3","周三");
        map.put("4","周四");
        map.put("5","周五");
        map.put("6","周六");
        map.put("7","周日");
        return map;
    }
}
